import { message } from "antd";
import { saveAs } from "file-saver";
import * as XLSX from "xlsx";
import type { WorkBook } from "xlsx";
import XLSXStyle from "xlsx-style-vite";
import XLSX_SAVE from "file-saver";
import { isEmptyString, isNotEmptyObject } from "./common";
import { SEX_VALUE } from "@/concacts/valueEnum";

const DEF_FILE_NAME = "excel-list.xlsx";

export interface HeaderData {
  list: any[];
  merges: any[];
  maxDepth: number;
}

export type ExportParamType = {
  columns: any[];
  data: any[];
  fileName: string;
  exportColumnFormat?: ExportColumnFormatType;
  write2excelOpts?: { bookType: "xlsx" };
  merges?: any[];
};

export type ExportColumnFormatType = (key: any, value: any) => void;

/**
 * @Description: 导出
 * @Author: ZhangHan
 * @Date: 2025-05-24 17:52:09
 */

export function excelExport(params: ExportParamType) {
  const { columns, data, fileName, exportColumnFormat, merges = [] } = params;
  if (!data || data.length == 0) {
    message.error("没有数据，无法导出");
    return;
  }
  const hasHeaderTitle = fileName != DEF_FILE_NAME;
  const write2excelOpts = params.write2excelOpts || { bookType: "xlsx" };

  //获取表格的每个字段对应的头部
  const header = columns.map((item) => item.title);

  //表格数据
  const dataTable = getSheetData(data, columns, exportColumnFormat);

  //总数据
  const arrData = [header, ...dataTable];

  const headerData = getSheetHeaderData(columns);

  if (headerData?.list) {
    arrData.unshift(...headerData.list);

    // 根据导出文件名称生成表头
    if (fileName != DEF_FILE_NAME) {
      const headerTitle: any[] = [];
      headerData.list?.[0]?.forEach(() => {
        headerTitle.push(fileName);
      });
      arrData.unshift(headerTitle);

      // 表格内容合并信息修正
      merges.forEach((item) => {
        item.s = { r: item.s.r + headerData.maxDepth, c: item.s.c };
        item.e = { r: item.e.r + headerData.maxDepth, c: item.e.c };
      });
      merges.push({
        s: { r: 0, c: 0 },
        e: { r: 0, c: headerData.list?.[0]?.length - 1 },
      });
      // 表格标题合并信息
      merges.push(...headerData.merges);
    }
  }

  // 创建工作簿
  const worksheet = XLSX.utils.aoa_to_sheet([header, ...dataTable]);

  /* add worksheet to workbook */
  const workbook: WorkBook = {
    SheetNames: [fileName],
    Sheets: {
      [fileName]: worksheet,
    },
  };

  // 设置列宽
  arrData.forEach((row, rowIndex) => {
    row.forEach((cell, cellIndex) => {
      const list = arrData.map((item, index) => {
        if (hasHeaderTitle && index === 0) return 1; // 表头行不设置列宽
        if (hasHeaderTitle && index >= 1) return 1; // 表头行不设置列宽

        const val = item[cellIndex] as string;
        if (isEmptyString(val)) {
          return 1;
        } else if (val.toString().charCodeAt(0) > 255) {
          // 判断是否有中文
          return val.toString().length * 2;
        } else {
          return val.toString().length;
        }
      });
      const maxLength = Math.max(...list);
      const width = maxLength < 8 ? 8 : maxLength * 1.1; // 根据实际内容长度自动调整列宽
      if (!worksheet["!cols"]) worksheet["!cols"] = [];
      if (!worksheet["!cols"][cellIndex])
        worksheet["!cols"][cellIndex] = { wch: 8 };
      worksheet["!cols"][cellIndex].wch = width; // 使用worksheet的 '!cols' 来设置列宽

      // 设置所有单元格样式
      const column = XLSX.utils.encode_cell({ c: cellIndex, r: rowIndex });
      if (!worksheet[column]) worksheet[column] = { v: "" };
      // 表头行设置背景色、加粗展示
      if (hasHeaderTitle && rowIndex === 0) {
        worksheet[column].s = getHeaderTitleStyle();
      }
      // 标题行设置背景色、加粗展示
      else if (
        (!hasHeaderTitle && rowIndex === 0) ||
        (hasHeaderTitle && rowIndex >= 1)
      ) {
        worksheet[column].s = getHeaderStyle();
      } else {
        worksheet[column].s = getDefaultCellStyle();
      }
    });
  });

    // 合并单元格
  merges.forEach((item) => {
    if(!worksheet["!merges"]){
      worksheet["!merges"] = [];
    };
    worksheet["!merges"].push(item);
    // worksheet["!merges"].push({
    //   s: { r: 2, c: 1 }, // s ("start"): c = 1 r = 2 -> "B3"
    //   e: { r: 3, c: 4 }  // e ("end"):   c = 4 r = 3 -> "E4"
    // });
  });

  // const wb = XLSX.utils.book_new();
  // XLSX.utils.book_append_sheet(wb, worksheet, fileName);

  // // 生成文件并保存
  // const buffer = XLSX.write(wb, { bookType: "xlsx", type: "array" });
  // const blob = new Blob([buffer], { type: "application/octet-stream" });
  // saveAs(blob, `${fileName}.xlsx`);
  const wbout = XLSXStyle.write(workbook, {
    type: "binary",
    bookType: "xlsx",
  });
  XLSX_SAVE.saveAs(
    new Blob([s2ab(wbout)], {
      type: "application/octet-stream",
    }),
    `${fileName}.${write2excelOpts.bookType}`
  );
}

// 数据转换
function s2ab(s) {
  const buf = new ArrayBuffer(s.length);
  const view = new Uint8Array(buf);
  for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
  return buf;
}

/**
 * @Description: 获取表单数据
 * @Author: knight
 * @Date: 2021/5/7 16:30
 */
function getSheetData(
  data: any[],
  columns: any[],
  exportColumnFormat?: ExportColumnFormatType
) {
  const dataTable: any = [];
  data.forEach((item: any) => {
    let obj = transformData(columns, item, exportColumnFormat);
    obj = Object.keys(obj).map((key) => obj[key]);
    dataTable.push(obj);
  });
  return dataTable;
}

/**
 * @Description: 转换表单数据
 * @Author: knight
 * @Date: 2021/5/7 16:30
 */
function transformData(
  columns: any[],
  value: any,
  exportColumnFormat?: ExportColumnFormatType
) {
  let obj = {};
  columns.forEach((item: any) => {
    const data = {};
    const key: any = item.key || item.dataIndex;

    if (key && typeof key === "string") {
      switch (key) {
        case "age": {
          data[key] = isNotEmptyObject(value?.age) ? value?.age : value?.age;
          break;
        }

        case "sex": {
          data[key] = SEX_VALUE[value?.sex]?.text;
          break;
        }

        default: {
          if (item.dataIndex && typeof item.dataIndex === "string") {
            if (item.valueEnum) {
              data[key] = item.valueEnum[value[item.dataIndex]]?.text;
            } else {
              data[key] = value[item.dataIndex];
            }
          }
        }
      }

      // 自定义格式化方法
      if (exportColumnFormat) {
        const ret = exportColumnFormat(key, value);
        if (isNotEmptyObject(ret)) {
          data[key] = ret;
        }
      }
    }

    obj = { ...obj, ...data };
  });
  return obj;
}

/**
 * @Description: 获取sheetHeaderData（支持多行，支持合并标题）
 * @Author: knight
 * @Date: 2024-05-20 14:47:33
 */
function getSheetHeaderData(columns: any[]): HeaderData {
  const result: HeaderData = {
    list: [],
    merges: [],
    maxDepth: 1,
  };

  const maxDepth = calculateMaxDepth(columns);
  console.log(`The maximum depth of the tree is: ${maxDepth}`);
  for (let i = 0; i < maxDepth; i++) {
    result.list.push([]);
  }
  result.maxDepth = maxDepth;

  // const totalDescendantsCount = columns.reduce((sum, item) => sum + countNodes(item), 0);
  // console.log(`The total number of descendants is: ${totalDescendantsCount}`);

  columns.forEach((item: any) => {
    getListData(result, item);
  });

  return result;
}

/**
 * @Description: 计算行数（最大深度）
 * @Author: knight
 * @Date: 2024-05-20 14:09:25
 */
function calculateMaxDepth(data) {
  // 递归辅助函数
  function traverse(node, depth = 1) {
    if (!node.children || node.children.length === 0) {
      // 如果没有子节点，返回当前深度
      return depth;
    }

    // 遍历每个子节点，并返回最大深度
    let maxChildDepth = 0;
    for (const child of node.children) {
      const childDepth = traverse(child, depth + 1);
      if (childDepth > maxChildDepth) {
        maxChildDepth = childDepth;
      }
    }
    return maxChildDepth;
  }

  // 遍历数据中的每个一级标题（节点）并找到最大深度
  let maxDepth = 0;
  for (const item of data) {
    const itemDepth = traverse(item);
    if (itemDepth > maxDepth) {
      maxDepth = itemDepth;
    }
  }

  return maxDepth;
}

/**
 * @Description: 计算并填充标题内容
 * @Author: knight
 * @Date: 2024-05-20 15:21:11
 */
function getListData(result, item, depth = 1) {
  let count = 0; // 初始计数为0

  // 如果节点有children并且children不为空数组
  if (
    item.children &&
    Array.isArray(item.children) &&
    item.children.length > 0
  ) {
    // 递归计算子节点的数量
    for (const child of item.children) {
      count += getListData(result, child, depth + 1); // 累加子节点的数量
    }
  } else {
    // 如果没有children或者children为空数组，节点计为一个
    count += 1;
  }

  if (count === 1) {
    for (let i = depth; i <= result.maxDepth; i++) {
      result.list[i - 1].push(item.title);
    }
    result.merges.push({
      s: { r: depth, c: result.list[depth - 1].length - 1 }, // s ("start"): c = 1 r = 2 -> "B3"
      e: { r: result.maxDepth, c: result.list[depth - 1].length - 1 }, // e ("end"):   c = 4 r = 3 -> "E4"
    });
  } else {
    for (let i = 0; i < count; i++) {
      result.list[depth - 1].push(item.title);
    }
    result.merges.push({
      s: { r: depth, c: result.list[depth - 1].length - count }, // s ("start"): c = 1 r = 2 -> "B3"
      e: { r: depth, c: result.list[depth - 1].length - 1 }, // e ("end"):   c = 4 r = 3 -> "E4"
    });
  }

  return count;
}

//单元格外侧框线
const borderAll = {
  top: {
    style: "thin",
  },
  bottom: {
    style: "thin",
  },
  left: {
    style: "thin",
  },
  right: {
    style: "thin",
  },
};

// 获取表头样式
const getHeaderTitleStyle = () => ({
  // border: borderAll,
  font: {
    name: "微软雅黑",
    sz: 16,
    color: { rgb: "000000" },
    bold: true,
    italic: false,
    underline: false,
  },
  fill: {
    fgColor: { rgb: "D0D0D0" },
  },
  alignment: {
    horizontal: "center",
    vertical: "center",
    wrapText: false, // 自动换行
  },
});

// 获取标题样式
const getHeaderStyle = () => ({
  border: borderAll,
  font: {
    // name: "微软雅黑",
    // sz: 16,
    color: { rgb: "000000" },
    bold: true,
    italic: false,
    underline: false,
  },
  fill: {
    fgColor: { rgb: "C5D9F1" },
  },
  alignment: {
    horizontal: "center",
    vertical: "center",
    wrapText: false, // 自动换行
  },
});

// 获取默认单元格样式
const getDefaultCellStyle = () => ({
  border: borderAll,
  alignment: {
    horizontal: "center",
    vertical: "center",
    wrapText: false, // 自动换行
  },
});
